package tbs.framework.async.task;

import org.jetbrains.annotations.NotNull;
import tbs.framework.async.container.IAsyncTaskService;
import tbs.framework.utils.TryCatchUtils;

/**
 * @author abstergo
 */
public abstract class AbstractAsyncTask implements IAsyncTask, ICancelable, IProgressable {

    private final String taskId;
    private boolean _isRunning;
    private boolean _isCanceled = false;
    private int _progress = 0;
    private int _max = 100;
    private String _cancelMsg;

    public AbstractAsyncTask(String taskId) {
        this.taskId = taskId;
    }

    @Override
    public @NotNull String taskId() {
        return taskId;
    }

    @Override
    public void execute(@NotNull IAsyncTaskService container) throws Throwable {
        _isCanceled = false;
        _isRunning = true;
        TryCatchUtils.tryCatch(() -> {
            task(container);
        }, null, () -> {
            _isRunning = false;
        });
    }

    /**
     * 具体任务实现
     *
     * @param container 异步任务服务
     * @throws Throwable 异常
     */
    protected abstract void task(@NotNull IAsyncTaskService container) throws Throwable;

    @Override
    public boolean isRunning() {
        return _isRunning;
    }

    @Override
    public void cancel(String cancelMsg) {
        if (isCanceled()) {
            throw new RuntimeException("Task is canceled");
        }
        _cancelMsg = cancelMsg;
        _isCanceled = true;
    }

    @Override
    public boolean isCanceled() {
        return _isCanceled;
    }

    @Override
    public String cancelReason() {
        return _cancelMsg;
    }

    @Override
    public void setProgress(int progress) {
        if (progress > _max) {
            _progress = _max;
        } else if (progress < 0) {
            _progress = 0;
        } else {
            _progress = progress;
        }
    }

    @Override
    public int getProgress() {
        return _progress;
    }

    @Override
    public int getMaxProgress() {
        return _max;
    }
}
